package profitcalc;

import java.util.Calendar;

import trading.Parameters;
import trading.data.Controller;
import trading.data.IDataType;
import trading.data.IStockTickDataCollection;
import trading.formulas.MACD;
import trading.strategy.ITradingStrategy;
import trading.strategy.MACDStrategy;

public class ProfitCalc 
{
	final private static float INIT_FUND = 100000;
	
	/**
	 * 1. init trading strategy parameters
	 * 2. set period
	 * 3. additional trading rule
	 * 4. parameters tuning
	 */
	
	private ITradingStrategy strategy;
	private ITradingStrategy additionalStrategy;
	private Calendar start;
	private Calendar end;
	private IStockTickDataCollection dataCollection;
	
	public ProfitCalc(IStockTickDataCollection dataCollection, ITradingStrategy strategy, Calendar start, Calendar end)
	{
		this.strategy = strategy;
		this.start = start;
		this.end = end;
		this.dataCollection = dataCollection;
	}
	
	public ProfitCalc(IStockTickDataCollection dataCollection, ITradingStrategy strategy, Calendar start, Calendar end, ITradingStrategy additionalStategy)
	{
		this(dataCollection, strategy, start, end);
		this.additionalStrategy = additionalStategy;
	}
	
	public ITradingStrategy getStrategy()
	{
		return this.strategy;
	}
	
	public ITradingStrategy getAdditionalStrategy()
	{
		return this.additionalStrategy;
	}
	
	/**
	 * 
	 * @return profit percent
	 */
	public float calculateProfit()
	{
		int start_idx = Controller.getIndex(dataCollection, start, true);
		int end_idx = Controller.getIndex(dataCollection, end, false);
		
		float fund = INIT_FUND;
		int stockAmount = 0;
		boolean buy = false;
		int buyAmount = 0;
		int saleAmount = 0;
		float buyPrice = 0;
		for(int i = start_idx; i<= end_idx; i++)
		{
			float price = Controller.getValueOn(dataCollection, i, IDataType.CLOSE_NAME);
			Calendar cal = dataCollection.getTickDataList().get(i); 
			if(strategy.shouldBuy(dataCollection, i) && !buy)
			{
				stockAmount = ((int)(fund/price))/100 * 100;
				fund -= stockAmount * price;
				
//				System.out.println("Buy at price : " + price + " on " + cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH) + 1) + "/" +cal.get(Calendar.DATE));
				buy = true;
				buyPrice = price;
				buyAmount ++;
			}
			
			if(strategy.shouldSale(dataCollection, i) && buy)
			{
				float profit = stockAmount * (price - buyPrice);
				fund += stockAmount * price;
//				System.out.println("Sale at price : " + price + " on " + cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH ) + 1) + "/" +cal.get(Calendar.DATE) + " Profit : " + profit);
				buy = false;
				saleAmount++;
			}
		}
		
//		System.out.println("Buy " + buyAmount + " times");
//		System.out.println("Sale " + buyAmount + " times");
		
		float price = Controller.getValueOn(dataCollection, end_idx, IDataType.CLOSE_NAME);
		fund += stockAmount * price;
		return fund/INIT_FUND * 100;
	}
	
	public static void main(String[] args) {
		Calendar start = Controller.createZeroCaledar();
		start.set(2006, 4 - 1, 28);
		Calendar end = Controller.createZeroCaledar();
		end.set(2009, 8 - 1, 24);
		
		IStockTickDataCollection dataCollection = Controller.getTickData();
		MACDStrategy strategy = MACDStrategy.getMACDStrategy();
		Parameters param = strategy.getParameters();
		param.setParamValue(MACD.LONG_IDX, 224);
		param.setParamValue(MACD.SHORT_IDX, 60);
		param.setParamValue(MACD.M_IDX, 2);
		
		ProfitCalc pc = new ProfitCalc(dataCollection, strategy, start, end);
		long time1 = System.currentTimeMillis();
		System.out.println(pc.calculateProfit());
		System.out.println(System.currentTimeMillis() - time1);
	}
	
}
